前面兩天有提到 Facade 和 Adapter 兩種設計模式,裡面的範例程式碼內容基本上是環繞在三個物件導向中的基礎概念:物件、封裝、抽象類別。今天的主要目的就是希望從理解設計模式的角度出發,用全新的方式來看待物件導向設計。
以下是本篇主要的內容:
傳統上物件被視為具有方法的資料,也就是一個包含著一些欄位、屬性以及方法的類別(我原本也就這麼認為XD),但如果回想一下 DAY3 討論範型時提到,我們將如何到下一堂上課教室的責任,從老師身上轉移到學生本身,最大的重點就是『責任』。
從概念視角出發 — 物件是具有責任的一個實體,這些責任定義了物件的行為,還能夠將物件視為具有特定行為的實體。
回顧一下:
public class Program
{
static void Main(string[] args)
{
// 我們給學生一個「去下一間教室」的規定,學生使用自己的方式到下一間教室
Student student = new Student();
student.goNextClassRoom();
}
}
public class Student : IStudentRule
{
// 介面有定義的屬性與方法名稱一定要實作
public string transportationType { get; set; }
public void goNextClassRoom()
{
transportationType = "腳踏車";
Console.WriteLine($"我使用{transportationType}到下一間教室");
}
}
public interface IStudentRule
{
// 介面定義好需要的屬性與方法名稱
string transportationType { get; set; }
void goNextClassRoom();
}
我們透過 IStudentRule
(規範) 讓學生去繼承,因此學生們知道他們要做什麼,並且需要為此負責,實作的部分就交給學生自己去處理,我們不用知道,只需要去注意定義好的介面是不是學生真的要去負責的東西,因此,真正需要去關注的是「動機」而非實作。
在傳統看法中封裝就是看成「資料隱藏」,但封裝其實應該被視為「任何形式的隱藏」,可以如下:
讓我們用UML來看看
下圖是在 DAY7 的 Adapter 範例模型
我們將他稍微小改一下
現在電腦裡所有的外接口我讓他們都繼承自 Output
這個介面,而螢幕直接使用這個介面就好,他再也不用管要用哪個接口,如果今天螢幕的外接頭換成了AVG,一樣也是對到 Output
即可。
在這張改過的UML圖裡,可以分成很多種層次的封裝:
DisplayPort
、USB
及HDMI
物件中的資料對其他所有物件來說都是隱藏的。HDMI
之外,其他物件對 TypecToHdmiAdapter
物件是一無所知的。Screen
看不到 DisplayPort
、USB
及HDMI
物件,他只知道 Output
。如果仔細看會發現, TypecToHdmiAdapter
這個物件實際上是一個『特殊化類別』,也就是為了做到某些特殊的事情而產生的。假設今天我變成是 AVG 的外接口想要去轉成 HDMI,那是不是就要再多一個 AvgToHdmiAdapter
的類別出來並且一樣去繼承 HDMI
,這就是特殊化物件會帶來的問題:
至於如何去解決這個問題,大家可以來思考一下,明天會來解答!